package GUI;

import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;

import javax.swing.JPanel;
import javax.swing.Timer;

import Linguo.Mapa;
import Objetos.Coleccionable;
import Objetos.Destructible;
import Objetos.Disparo;
import Objetos.Elemento;
import Objetos.Intransitable;
import Objetos.Premio;


/**
 * Clase GUIJuego que se encarga de pintar el nivel que se jugara.
 * @author Andres Garcia Amado, Federico Quattrocchio, Matias Lameiro
 */
@SuppressWarnings("serial")
public class GUIJuego extends JPanel implements ActionListener{

	/** Mapa */
	protected Mapa m; 

	/** Timer. */
	protected Timer timer;

	/** La interfaz principal */
	protected GUI gui;

	/** Ruta del nivel */
	String lvlName;

	/** Audio del juego. */

	/**
	 * Constructor de la clase GUIJuego
	 *
	 * @param g la GUI principal
	 * @param nivel Arreglo con en el nivel que se jugara
	 * @param tipoRobot el tipo de robot
	 */
	public GUIJuego(GUI g,String [] nivel, String tipoRobot) {
		gui = g;
		this.lvlName = "src/Niveles/"+lvlName+".txt";
//		try {
//			audio= new Audio();
//			audio.doPlay("/Audio/Hydrogen.wav");
//		} catch (Exception e1) {}
		addKeyListener(new TAdapter());
		this.setFocusable(true);
		
		m = new Mapa(this,nivel,tipoRobot);

		timer = new Timer(15, this);
		timer.start();

	
	}



	/**
	 * Construye el mundo del juego.
	 *
	 * @param g los Graphics
	 */
	public void buildWorld(Graphics g) {

		g.setColor(new Color(250, 240, 170));
		g.fillRect(0, 0, this.getWidth(), this.getHeight());

		ArrayList<Elemento> world = new ArrayList<Elemento>();
		world.addAll(m.getTransitables());
		world.addAll(m.getPremios());
		world.addAll(m.getIntransitables());
		world.addAll(m.getPinturas());
		world.addAll(m.getColeccionables());
		world.addAll(m.getDisparos());



		for(int i = 0 ; i<world.size() ; i++) {

			Elemento e = (Elemento) world.get(i);
			if(e.isVisible()) {
				g.drawImage(e.getImage(), e.getX(), e.getY(), this);
			}
		}


		g.drawImage(m.getMapeo().get("fin").getImage(), m.getxFinal(), m.getyFinal(), this);

		world.add(m.getRobot());
		g.drawImage(m.getRobot().getImage(), m.getRobot().getX(), m.getRobot().getY(), this);

		for(int i = 0 ; i<m.getDestructibles().size() ; i++) {
			Destructible d = m.getDestructibles().get(i);
			if(!d.isVisible()) {
				m.getDestructibles().remove(d);
			}
		}

		for(int i = 0 ; i<m.getColeccionables().size() ; i++) {
			Coleccionable d = m.getColeccionables().get(i);
			if(!d.isVisible()) {
				m.getColeccionables().remove(d);
			}
		}

		for(int i = 0 ; i<m.getIntransitables().size() ; i++) {
			Intransitable d = m.getIntransitables().get(i);
			if(!d.isVisible()) {
				m.getIntransitables().remove(d);
			}
		}

		for(int i = 0 ; i<m.getPremios().size() ; i++) {
			Premio p = m.getPremios().get(i);
			if(!p.isVisible()) {
				m.getPremios().remove(p);
				gui.actualizarPuntos();
				gui.actualizarNafta();
				gui.actualizarBalas();
			}
		}


		ArrayList<Disparo> ds = m.getDisparos();

		for (int i = 0; i < ds.size(); i++ ) {
			Disparo d = (Disparo) ds.get(i);
			if(!d.isVisible()) {
				ds.remove(d);
			}
		}


		if(m.getCompleted()) {
		
			String msg = "Nivel Completado";
			Font small = new Font("Arial", Font.BOLD, 20);
			FontMetrics metr = this.getFontMetrics(small);

			g.setColor(Color.black);
			g.setFont(small);
			g.drawString(msg, (m.getW() - metr.stringWidth(msg)) / 2, m.getH() / 2);
	
			
		}
		else {
			if(!m.getRobot().puedeAvanzar()) {
				String msg = "Se quedo sin Nafta. R para reiniciar el nivel";
				Font small = new Font("Arial", Font.BOLD, 20);
				FontMetrics metr = this.getFontMetrics(small);

				g.setColor(Color.black);
				g.setFont(small);
				g.drawString(msg, (m.getW() - metr.stringWidth(msg)) / 2, m.getH() / 2);
			}
		}

	}

	/* (non-Javadoc)
	 * @see javax.swing.JComponent#paint(java.awt.Graphics)
	 */
	public void paint(Graphics g) {
		super.paint(g);
		buildWorld(g);
	}

	/**
	 * CLase TAdapter que posee se encarga de recibir los eventos del teclado y hacer lo que corresponda segun que se presiono.
	 */
	class TAdapter extends KeyAdapter {

		/* (non-Javadoc)
		 * @see java.awt.event.KeyAdapter#keyPressed(java.awt.event.KeyEvent)
		 */
		@Override
		public void keyPressed(KeyEvent e) {

			int key = e.getKeyCode();
			if (m.getCompleted()) {
				///////////////////////////////SI PRESIONA R////////////////////////////////////////////////////////
				if (key == KeyEvent.VK_R)
					m.restartLevel();
				else
					return;
			}

			//////////////////////////////////////SI SE PRESIONA FLECHA IZQUIERDA/////////////////////////////////////
			if (key == KeyEvent.VK_LEFT) {
				girarIzquierda();

			} 
			//////////////////////////////////////SI SE PRESIONA FLECHA DERECHA/////////////////////////////////////

			else if (key == KeyEvent.VK_RIGHT) {
				girarDerecha();

			} 
			//////////////////////////////////////SI SE PRESIONA FLECHA ARRIBA/////////////////////////////////////

			else if (key == KeyEvent.VK_UP) {
				avanzar();

			} 
			//////////////////////////////////////SI SE PRESIONA FLECHA ABAJO/////////////////////////////////////

			else if (key == KeyEvent.VK_DOWN) {
				agarrarDejar();
			} 
			else if (key == KeyEvent.VK_R) {
				m.restartLevel();
				gui.restartGui();
			} 
			else if (key == KeyEvent.VK_SPACE) {
				disparar();
			} 
			else if(key == KeyEvent.VK_B) {
				guardarBaul();
			}
			else if(key == KeyEvent.VK_P) {
				bajarSubirPincel();
			}
			else if(key == KeyEvent.VK_1) {
				pintarBlanco();
				gui.accionBotonPintarBlanco();

			}
			else if(key == KeyEvent.VK_2) {
				pintarNegro();
				gui.accionBotonPintarNegro();
			}

			
			m.isCompleted();
		}
	}

	/* (non-Javadoc)
	 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
	 */
	public void actionPerformed(ActionEvent e) {

		m.accion();
		repaint();  
	}

	/**
	 * Cambia la GUI principal.
	 *
	 * @param g la nueva GUI principal
	 */
	public void setGUI(GUI g) {
		gui = g;
	}

	/**
	 * Devuelve el mapa que se esta jugando.
	 *
	 * @return El mapa actual.
	 */
	public Mapa getMapa() {
		return m;
	}

	/**
	 * Actualiza nafta en la GUI principal.
	 */
	public void actualizarNafta() {
		gui.actualizarNafta();
	}

	/**
	 * Actualiza puntos en la GUI principal.
	 */
	public void actualizarPuntos() {
		gui.actualizarPuntos();
	}

	/**
	 * Actualiza balas en la GUI principal.
	 */
	public void actualizarBalas() {
		gui.actualizarBalas();
	}

	/**
	 * Actualiza item en brazo en la GUI principal.
	 */
	public void actualizarItemEnBrazo() {
		gui.actualizarItemEnBrazo();
	}

	/**
	 * Hace disparar al robot y actualiza la etiqueta de la cantidad de balas en la GUI principal.
	 */
	public void disparar(){
		m.getRobot().fire();
		gui.actualizarBalas();
	}

	/**
	 * Hace girar a la derecha al robot y actualiza la etiqueta de la cantidad de nafta en la GUI principal.
	 */
	public void girarDerecha(){
		m.getRobot().girarDerecha();
		gui.actualizarNafta();
	}

	/**
	 * Hace girar a la izquierda al robot y actualiza la etiqueta de la cantidad de nafta en la GUI principal.
	 */
	public void girarIzquierda(){
		m.getRobot().girarIzquierda();
		gui.actualizarNafta();
	}

	/**
	 * Hace avanzar al robot y actualiza la etiqueta de la cantidad de nafta en la GUI principal.
	 */
	public void avanzar(){
		m.getRobot().move();
		gui.actualizarNafta();
		m.isCompleted();
	}

	/**
	 * Pintar blanco.
	 */
	public void pintarBlanco(){
		m.getRobot().setColor("blanco");
	}

	/**
	 * Setea en blanco el color del pincel del robot.
	 */
	public void pintarNegro(){
		m.getRobot().setColor("negro");
	}

	/**
	 * Agarra o deja un item del suelo segun corresponda.
	 */
	public void agarrarDejar(){
		if (m.getRobot().getItemEnBrazo()== null)
			m.getRobot().agarrar();
		else m.getRobot().dejarItem();
		gui.actualizarItemEnBrazo();

	}

	/**
	 * Cambia el estado del pincel del robot. Lo baja si esta levantado o lo levanta si esta bajo.
	 */
	public void bajarSubirPincel(){
		m.getRobot().setPincel(!m.getRobot().getPincel());
	}

	/**
	 * Guarda el item en el brazo del robot en su baul.
	 */
	public void guardarBaul(){
		if(m.getRobot().getItemEnBrazo()!=null) {
			m.getRobot().guardarBaul();
			gui.actualizarBaul();
			gui.actualizarItemEnBrazo();
		}
	}

	/**
	 * Actualiza las etiquetas de los items en el baul del robot de la GUI principal.
	 */
	public void actualizarBaul(){
		gui.actualizarBaul();
	}

	public void cambiarMusica(final String url) {
		gui.cambiarMusica(url);
	}

}
